import 'package:flutter/material.dart';

/*
* 通知（Notification）是Flutter中一个重要的机制，在widget树中，每一个节点都可以分发通知，
* 通知会沿着当前节点向上传递，所有父节点都可以通过NotificationListener来监听通知。
* Flutter中将这种由子向父的传递通知的机制称为通知冒泡（Notification Bubbling）。
* 通知冒泡和用户触摸事件冒泡是相似的，但有一点不同：通知冒泡可以中止，但用户触摸事件不行。
* */


class NotificationApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: Scaffold(
//        body:SimpleNo(),
        body: NotificationRoute(),
      ),
    );
  }
}

/******************自定义通知********************/
class SimpleNo extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return  NotificationListener<ScrollNotification>(
      onNotification: (notification){
        print(notification);
      },
      child: ListView.builder(
          itemCount: 30,
          itemBuilder: (context,index){
            return ListTile(title: Text("$index"),);
          }),);
  }
}

class NotificationRoute extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return NotificationRouteState();
  }
}

class NotificationRouteState extends State<NotificationRoute>{
  String _msg = "";

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    //监听通知
    return NotificationListener<MyNotification>(
      onNotification: (notification){
        setState(() {
          _msg += notification.msg+" ";
        });
//        return true;
        return false;/******************阻止冒泡*******************/
      },
      child: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Builder(builder: (context){
              return RaisedButton(
                child: Text("Send Notification"),
                  //按钮点击时分发通知
                  onPressed: ()=>MyNotification("Hi~").dispatch(context));
            }),
            Text(_msg),
          ],
        ),
      ),
    );
  }
}

class MyNotification extends Notification{
  MyNotification(this.msg);
  final String msg;
}

/*
* 我们可以看到NotificationListener的onNotification回调最终是在_dispatch方法中执行的，
* 然后会根据返回值来确定是否继续向上冒泡。上面的源码实现其实并不复杂，通过阅读这些源码，
* 一些额外的点读者可以注意一下：

Context上也提供了遍历Element树的方法。
我们可以通过Element.widget得到element节点对应的widget；我们已经反复讲过Widget和Element的对应关系，
读者通过这些源码来加深理解。
* */

/*
* 总结

Flutter中通过通知冒泡实现了一套自低向上的消息传递机制，这个和Web开发中浏览器的事件冒泡原理类似，
Web开发者可以类比学习。另外我们通过源码了解了Flutter 通知冒泡的流程和原理，便于读者加深理解和
学习Flutter的框架设计思想，在此，再次建议读者在平时学习中能多看看源码，定会受益匪浅。
* */



